/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lbim.client.ui;

import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import lbim.client.main.MapUpdateListener;
import lbim.protocol.Controller;

/**
 *
 * @author Jestan
 */
public class MapCanvas extends GameCanvas implements MapUpdateListener, Runnable {
    private Controller controller;

    private LayerManager layerManager;
    private Sprite mapSprite;
    
    private int x;
    private int y;
    
    private int mapWidth;
    private int mapHeight;
    
    private int viewWidth;
    private int viewHeight;

    private int deltaX;
    private int deltaY;

    private int currentZoom = Controller.DEFAULT_MIN_ZOOM;
    
    private static final int MILLIS_PER_TICK=50;
    private Image mapImage;
    private Image loadingImage;
    private Thread thread;
    private volatile boolean isLoading;

    private MainUI ui_;

    public MapCanvas(Controller controller) {
        super(true);
        this.controller = controller;
        isLoading = true;
        viewWidth = this.getWidth();
        viewHeight = this.getHeight();
        layerManager = new LayerManager();
        ui_ = MainUI.getInstance();
        try {
            loadingImage = Image.createImage("/loading.png");
        } catch (IOException ex) {
            System.out.println("EEE");
        }
    }

    public void init() {
        thread = new Thread(this);
        thread.start();
    }

    public void run() {

        
        Thread currentThread = Thread.currentThread();
        try {
            while (currentThread == thread) {
                long startTime = System.currentTimeMillis();

                updateViewWindow();
                Graphics g = getGraphics();
                drawScreen(g);

                long timeTake = System.currentTimeMillis() - startTime;
                if (timeTake < MILLIS_PER_TICK) {
                    synchronized (this) {
                        wait(MILLIS_PER_TICK - timeTake);
                    }
                } else {
                    currentThread.yield();
                }
            }
        } catch (InterruptedException ex) {
        }
    }

    private void drawScreen(Graphics g) {
        if(isLoading) {
            g.drawImage(loadingImage, x , y , Graphics.TOP |Graphics.LEFT);
        }
        layerManager.paint(g, 0, 0);
	layerManager.setViewWindow(x, y, viewWidth, viewHeight);
        flushGraphics();
    }

    public void mapDataRecieved(byte[] data) {
        if (mapSprite != null) {
            layerManager.remove(mapSprite);
        }
        mapImage = Image.createImage(data, 0, data.length);
        mapSprite = new Sprite(mapImage);
        layerManager.append(mapSprite);

        this.mapWidth = mapImage.getWidth();
        this.mapHeight = mapImage.getHeight();

        this.deltaX = mapWidth - viewWidth;
        this.deltaY = mapHeight - viewHeight;

        this.x = deltaX/2;
        this.y = deltaY/2;

        isLoading = false;
        
        System.out.println("[MapCanvas] map image updated");
    }
    
    private void updateViewWindow() {
        int keyStates = this.getKeyStates();
        // Left
        if ((keyStates & LEFT_PRESSED) != 0) {
            if (x - 1 > 0) {
                x--;
            }
        } else if ((keyStates & RIGHT_PRESSED) != 0) {
            if (x + 1 < deltaX) {
                x++;
            }
        } else if ((keyStates & UP_PRESSED) != 0) {
            if (y - 1 > 0) {
                y--;
            }
        } else if ((keyStates & DOWN_PRESSED) != 0) {
            if (y + 1 < deltaY) {
                y++;
            }
        } else if ((keyStates & FIRE_PRESSED) != 0) {
                ui_.setView(MainUI.SCR_TABBED);
        }
    }

    public void keyPressed(int key) {
        switch (key) {
            case KEY_STAR:
                if (currentZoom + 1 < Controller.DEFAULT_MAX_ZOOM) {
                    currentZoom++;
                    alterZoomLevel();
                }
                break;
            case KEY_POUND:
                if (currentZoom - 1 > Controller.DEFAULT_MIN_ZOOM) {
                    currentZoom--;
                    alterZoomLevel();
                }
                break;
            
        }
    }

    private void alterZoomLevel() {
        isLoading = true;
        controller.sendLocationUpdate(currentZoom);
    }

    public void locationUpdated() {
        isLoading = true;
        System.out.println("[MapCanvas] user is moving...map image updated");
        controller.sendLocationUpdate(currentZoom);
    }

    public void deviceStateChanged(int state) {
        //draw some bar..
        System.out.println("[MapCanvas] gps device status changed");
    }

}
